(function(angular) {
	'use strict';
	angular.module('fs.waf').factory('ppfCommunityService', ppfCommunityService);
	ppfCommunityService.$inject = [ '$q', '$timeout', 'loggerFactory', 'ajaxServiceFactory', 'modalService', 'gridService', 'arithService', '$filter', 'profFilterOptionService' ];
	function ppfCommunityService($q, $timeout, loggerFactory, ajaxServiceFactory, modalService, gridService, arithService, $filter, profFilterOptionService) {
		var log = loggerFactory.getLogger("ppfCommunityService"), ajaxService = ajaxServiceFactory.buildAjaxService({
			getCommunityStatusOptions: {
				url : 'do/cda/dataList/communityStatuses',
				method : 'get'					
			},
			getCommunityCodeQOptions: {
				url : 'do/cda/dataList/communityCodeQs',
				method : 'get'					
			},
			getPpfCommunityOptions : {
				url : 'do/cda/dataList/ppfCommunityOptions',
				method : 'get'
			},
			getLayoutConfigByProdType: {
				url : 'do/cda/ppfCommunity/layout',
				method : 'post'					
			},
		});
		
		function initGeneral($scope, ctrl, updateProcessFlag) {
			var defer = $q.defer();
			profFilterOptionService.initProfFilterOptions(ctrl).then(function() {
				getPpfCommunityOptions().then(function(response) {
					ctrl.allProdSubtypeOptions = response.allProdSubtypeOptions;
					ctrl.invoiceAmtCcyOptions = angular.copy(response.currenciesOptions);
					ctrl.yesNoOptions = response.yesNoOptions;
					ctrl.tenorProcFlagOptions = response.tenorProcFlagOptions;
					ctrl.communityStatusOptions = response.communityStatusOptions;	
					ctrl.billFreqTypeOptions = response.billFreqTypeOptions;
					ctrl.feeCodeListOptions = response.feeCodeListOptions;
					ctrl.chargebackSetlTypeOptions = response.chargebackSetlTypeOptions;
					ctrl.paySchdTypeOptions = response.paySchdTypeOptions;
					ctrl.invoiceEmdDaysTypeOptions = response.invoiceEmdDaysTypeOptions;
					ctrl.communityCodeQOptions = response.communityCodeQOptions;
//					ctrl.financeCatOptions = response.financeCatOptions;
//					ctrl.statementPeriodOptions = response.statementPeriodOptions;
//					ctrl.statementFreqOptions = response.statementFreqOptions;
//					ctrl.statementPeriodtypeOptions = response.statementPeriodtypeOptions;
//					ctrl.statementFormatOptions = response.statementFormatOptions;
					ctrl.allProdCodes = response.allProdCodes;
					ctrl.prodCodeOptions = ctrl.allProdCodes;
					// for profSetlinst
					ctrl.txnCcyOptions = angular.copy(response.currencyByFxRateOptions);
					ctrl.setlCcyOptions = angular.copy(response.currencyByFxRateOptions);
					ctrl.crDrOptions = response.crDrOptions;
					ctrl.allPaycodeOptions = response.allPaycodeOptions;
					ctrl.itemTypeOptions = response.itemTypeOptions;
					ctrl.intCatOptions = response.intCatOptions;// multi interest
					ctrl.facilityCatOptions = response.facilityCatOptions;// multi limit facility category
					defer.resolve();
				}, angular.noop);
			});
			
			ctrl.chargebackSusAcctCallback = function(lookupResult, ppfCommunity) {
				var tmp = ctrl.ppfCommunity.profChargeback.chargebackSusAcct;
				ctrl.ppfCommunity.profChargeback.chargebackSusAcct = $filter('encode')(tmp);
			};
			
			ctrl.buyerCodeChanged = function(value) {
				if (ctrl.ppfCommunity.buyerCode) {
					ctrl.custCodeParam = ctrl.ppfCommunity.buyerCode;
				}
				if (ctrl.ppfCommunity.prodSubtype && ctrl.ppfCommunity.prodSubtype != ctrl.ppfCommunity.oldProdSubtype) {
					ctrl.ppfCommunity.oldProdSubtype = ctrl.ppfCommunity.prodSubtype;
					for (var i = 0; i < ctrl.allProdSubtypeOptions.length; i++) {
						var _prodSubtype = ctrl.allProdSubtypeOptions[i];
						if (_prodSubtype.value == ctrl.ppfCommunity.prodSubtype) {
							resetCommunityByProdSubtypeExtProperty(ctrl, _prodSubtype, null);
							// create wf prodsubType can change
							changeLayoutConfig($scope, ctrl, ctrl.action);
							break;
						}
					}
				}
			};
			
			return defer.promise;
		}
		function getPpfCommunityOptions() {
			var defer = $q.defer();
			ajaxService.getPpfCommunityOptions().then(function(response) {
				var ppfCommunityOptions = {};
				if (response.data) {
					angular.forEach(response.data, function(value, key) {
						var tempValue = {};
						tempValue = value;
						ppfCommunityOptions[key] = tempValue;
					});
				}
				defer.resolve(ppfCommunityOptions);
			});
			return defer.promise;
		}
		
		function initLayoutConfigAndModel ($scope, ctrl, initPpfCommunity, action, updateProcessFlag) {
			var defer3 = $q.defer();
			if (initPpfCommunity.prodSubtype) {
				initPpfCommunity.oldProdSubtype = initPpfCommunity.prodSubtype;
				for (var i = 0; i < ctrl.allProdSubtypeOptions.length; i++) {
					var _prodSubtype = ctrl.allProdSubtypeOptions[i];
					if (_prodSubtype.value == initPpfCommunity.prodSubtype) {
						resetCommunityByProdSubtypeExtProperty(ctrl, _prodSubtype, initPpfCommunity);
						break;
					}
				}
				//
				var params = {};
				params.action = action;
				params.prodSubtype = initPpfCommunity.prodSubtypeExtProperty.prodSubtypeName;
				ajaxService.getLayoutConfigByProdType(params).then(function(response) {
					// $attrs.fsValidatorConfig change , then can update new $scope._fsValidatorConfig
					resetValidateByProdSubtype(ctrl, initPpfCommunity);
					// 1. change layout
					var newLayoutConfig = addLayoutConfigForMulti(ctrl, response.data);
					initMultiTableDefine(newLayoutConfig, $scope, ctrl, updateProcessFlag);
					ctrl.layoutConfig = newLayoutConfig;
					$timeout(function() {
						resetDataModel(ctrl, initPpfCommunity, updateProcessFlag);
						// reset model after change layout
						ctrl.ppfCommunity = initPpfCommunity;
						// reset cust prop data
						ctrl.resetCustProperties();
						defer3.resolve();
					});
				});
			}
			// create also get layout again for get all dynaparm by ppfCommunity
			// this will get '*'
			else if (action == 'create') {
				var params = {};
				params.action = action;
				params.prodSubtype = '';
				ajaxService.getLayoutConfigByProdType(params).then(function(response) {
					// $attrs.fsValidatorConfig change , then can update new $scope._fsValidatorConfig
					resetValidateByProdSubtype(ctrl, initPpfCommunity);
					// 1. change layout
					var newLayoutConfig = addLayoutConfigForMulti(ctrl, response.data);
					initMultiTableDefine(newLayoutConfig, $scope, ctrl, updateProcessFlag);
					ctrl.layoutConfig = newLayoutConfig;
					// reset model after change layout
					$timeout(function(){
						resetDataModel(ctrl, initPpfCommunity, updateProcessFlag);
						ctrl.ppfCommunity = initPpfCommunity;
						// reset cust prop data
						ctrl.resetCustProperties();
						defer3.resolve();
					});
				});
			}
			return defer3.promise;
		};
		
		function changeLayoutConfig ($scope, ctrl, action) {
			// $attrs.fsGridConfig change then can invoke prepareGridRules, it's used by ctrl.changeLayoutConfig, for trigger for add required or not
			ctrl.layoutConfig.formConfigs.profBilling = {};
			ctrl.layoutConfig.formConfigs.profChargeback = {};
			ctrl.layoutConfig.formConfigs.profPayschd = {};
			ctrl.layoutConfig.formConfigs.profInvfilter = {};
			if (ctrl.ppfCommunity.prodSubtype) {
				var params = {};
				params.action = action;
				params.prodSubtype = ctrl.ppfCommunity.prodSubtypeExtProperty.prodSubtypeName;
//				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				ajaxService.getLayoutConfigByProdType(params).then(function(response) {
					var tmp = angular.copy(ctrl.ppfCommunity);
					// $attrs.fsValidatorConfig change , then can update new $scope._fsValidatorConfig
					resetValidateByProdSubtype(ctrl);
					// 1. change layout
					// 2. $attrs.fsGridConfig change then also can invoke prepareGridRules, trigger for add required or not
					ctrl.layoutConfig = addLayoutConfigForMulti(ctrl, response.data);
					// reset model after change layout
					$timeout(function(){
						ctrl.ppfCommunity = tmp;
						// reset cust prop data
						ctrl.resetCustProperties();
					});
				});
			} 
		};
		
		function addLayoutConfigForMulti(ctrl, resLayoutConfig) {
			if (!resLayoutConfig) return resLayoutConfig;
			/**
			   "profInt": {
					"name": "profInt",
					"tableConfigs": {
						"table": {
							"name": "table",
							"enableOperation": true,
							"enableOperationRemoveSelected": true,
							"addRow": "vm.addProfInt",
							"editRow": "vm.editProfInt",
							"removeSelectedRows": "vm.removeProfInt",
							"columnDefs": [...]
						}
					}
				},
			 */
			var profIntLayoutTemplate = resLayoutConfig.formConfigs.profInt;
			if (ctrl.intCatOptions && ctrl.intCatOptions.length > 0) {
				for (var i = 0; i < ctrl.intCatOptions.length; i++) {
					var intCat = ctrl.intCatOptions[i].value;
					var layoutTmp = angular.copy(profIntLayoutTemplate);
					layoutTmp.name = 'profInt' + intCat;
					if (layoutTmp.tableConfigs.table.addRow)
						layoutTmp.tableConfigs.table.addRow = layoutTmp.tableConfigs.table.addRow + '.' + intCat;
					if (layoutTmp.tableConfigs.table.editRow)
						layoutTmp.tableConfigs.table.editRow = layoutTmp.tableConfigs.table.editRow + '.' + intCat;
					if (layoutTmp.tableConfigs.table.removeSelectedRows)
						layoutTmp.tableConfigs.table.removeSelectedRows = layoutTmp.tableConfigs.table.removeSelectedRows + '.' + intCat;
					if (layoutTmp.tableConfigs.table.viewRow)
						layoutTmp.tableConfigs.table.viewRow = layoutTmp.tableConfigs.table.viewRow + '.' + intCat;
					resLayoutConfig.formConfigs['profInt' + intCat] = layoutTmp;
				}
			}
			/**
			   "profLimitFaci": {
					"name": "profLimitFaci",
					"tableConfigs": {
						"table": {
							"name": "table",
							"enableOperation": true,
							"enableOperationRemoveSelected": true,
							"addRow": "vm.addProfLimitFaci",
							"editRow": "vm.editProfLimitFaci",
							"removeSelectedRows": "vm.removeProfLimitFaci",
							"columnDefs": [...]
						}
					}
				},
			 */
			var profLimitFaciLayoutTemplate = resLayoutConfig.formConfigs.profLimitFaci;
			if (ctrl.facilityCatOptions && ctrl.facilityCatOptions.length > 0) {
				for (var i = 0; i < ctrl.facilityCatOptions.length; i++) {
					var facilityCat = ctrl.facilityCatOptions[i].value;
					var layoutTmp = angular.copy(profLimitFaciLayoutTemplate);
					layoutTmp.name = 'profLimitFaci' + facilityCat;
					if (layoutTmp.tableConfigs.table.addRow)
						layoutTmp.tableConfigs.table.addRow = layoutTmp.tableConfigs.table.addRow + '.' + facilityCat;
					if (layoutTmp.tableConfigs.table.editRow)
						layoutTmp.tableConfigs.table.editRow = layoutTmp.tableConfigs.table.editRow + '.' + facilityCat;
					if (layoutTmp.tableConfigs.table.removeSelectedRows)
						layoutTmp.tableConfigs.table.removeSelectedRows = layoutTmp.tableConfigs.table.removeSelectedRows + '.' + facilityCat;
					if (layoutTmp.tableConfigs.table.viewRow)
						layoutTmp.tableConfigs.table.viewRow = layoutTmp.tableConfigs.table.viewRow + '.' + facilityCat;
					resLayoutConfig.formConfigs['profLimitFaci' + facilityCat] = layoutTmp;
				}
			}
			return resLayoutConfig;
		}
		
		function initMultiTableDefine(newLayoutConfig, $scope, ctrl, updateProcessFlag) {
			initMultiProfInt(newLayoutConfig, $scope, ctrl, updateProcessFlag);
			initMultiProfLimitFaci(newLayoutConfig, $scope, ctrl, updateProcessFlag);
		}
		
		/**
		 * build ppfCommunityTmp profInts
		 */
		function resetDataModel(ctrl, initPpfCommunity, updateProcessFlag) {
			var initPpfCommunityTmp = {};
			if (ctrl.intCatOptions && ctrl.intCatOptions.length > 0) {
				for (var i = 0; i < ctrl.intCatOptions.length; i++) {
					var intCat = ctrl.intCatOptions[i].value;
					var belongIntCatProfInts = [];
					if (initPpfCommunity.profInts && initPpfCommunity.profInts.length > 0) {
						for (var j = 0; j < initPpfCommunity.profInts.length; j++) {
							if (initPpfCommunity.profInts[j].intCat == intCat) {
								belongIntCatProfInts.push(initPpfCommunity.profInts[j]);
							}
						}
					}
					initPpfCommunityTmp['profInts' + intCat] = belongIntCatProfInts;
				}
			}
			if (ctrl.facilityCatOptions && ctrl.facilityCatOptions.length > 0) {
				for (var i = 0; i < ctrl.facilityCatOptions.length; i++) {
					var facilityCat = ctrl.facilityCatOptions[i].value;
					var belongFacilityCatProfLimitFacis = [];
					if (initPpfCommunity.profLimitFacis && initPpfCommunity.profLimitFacis.length > 0) {
						for (var j = 0; j < initPpfCommunity.profLimitFacis.length; j++) {
							if (initPpfCommunity.profLimitFacis[j].facilityCat == facilityCat) {
								belongFacilityCatProfLimitFacis.push(initPpfCommunity.profLimitFacis[j]);
							}
						}
					}
					initPpfCommunityTmp['profLimitFacis' + facilityCat] = belongFacilityCatProfLimitFacis;
				}
			}
			ctrl.ppfCommunityTmp =  initPpfCommunityTmp;
			
			if (ctrl.ppfCommunityOld && ctrl.ppfCommunityOld.profInts) {
				var initPpfCommunityOldTmp = {};
				if (ctrl.intCatOptions && ctrl.intCatOptions.length > 0) {
					for (var i = 0; i < ctrl.intCatOptions.length; i++) {
						var intCat = ctrl.intCatOptions[i].value;
						var belongIntCatProfInts = [];
						if (ctrl.ppfCommunityOld.profInts && ctrl.ppfCommunityOld.profInts.length > 0) {
							for (var j = 0; j < ctrl.ppfCommunityOld.profInts.length; j++) {
								if (ctrl.ppfCommunityOld.profInts[j].intCat == intCat) {
									belongIntCatProfInts.push(ctrl.ppfCommunityOld.profInts[j]);
								}
							}
						}
						initPpfCommunityOldTmp['profInts' + intCat] = belongIntCatProfInts;
					}
				}
				if (ctrl.facilityCatOptions && ctrl.facilityCatOptions.length > 0) {
					for (var i = 0; i < ctrl.facilityCatOptions.length; i++) {
						var facilityCat = ctrl.facilityCatOptions[i].value;
						var belongFacilityCatProfLimitFacis = [];
						if (ctrl.ppfCommunityOld.profLimitFacis && ctrl.ppfCommunityOld.profLimitFacis.length > 0) {
							for (var j = 0; j < ctrl.ppfCommunityOld.profLimitFacis.length; j++) {
								if (ctrl.ppfCommunityOld.profLimitFacis[j].facilityCat == facilityCat) {
									belongFacilityCatProfLimitFacis.push(ctrl.ppfCommunityOld.profLimitFacis[j]);
								}
							}
						}
						initPpfCommunityOldTmp['profLimitFacis' + facilityCat] = belongFacilityCatProfLimitFacis;
					}
				}
				ctrl.ppfCommunityOldTmp =  initPpfCommunityOldTmp;
			}
			
			resetSetlinstByData(initPpfCommunity, !updateProcessFlag);
		}
		
		/**
		 * reset validate
		 * in edit page some tabs(no popup) hidden, those tabs js validation need clear
		 * 
		 */
		function resetValidateByProdSubtype(ctrl, initPpfCommunity) {
			if (ctrl.initValidatorConfig) {
				var tmpPpfCommunity;
				if (initPpfCommunity) {
					tmpPpfCommunity = initPpfCommunity;
				} else {
					tmpPpfCommunity = ctrl.ppfCommunity;
				}
				ctrl.tmpValidatorConfig = angular.copy(ctrl.initValidatorConfig);
				if (!(tmpPpfCommunity.prodSubtypeExtProperty.ufcBilling == 'Y')) {
					ctrl.tmpValidatorConfig.profBilling = {};
				}
				if (!(tmpPpfCommunity.prodSubtypeExtProperty.ufcChargeback == 'Y')) {
					ctrl.tmpValidatorConfig.profChargeback = {};
				}
				if (!(tmpPpfCommunity.prodSubtypeExtProperty.ufcPayschd == 'Y')) {
					ctrl.tmpValidatorConfig.profPayschd = {};
				}
				if (!(tmpPpfCommunity.prodSubtypeExtProperty.ufcInvfilter == 'Y')) {
					ctrl.tmpValidatorConfig.profInvfilter = {};
				}
				ctrl.validatorConfig = ctrl.tmpValidatorConfig;
			}	
		}
		
		function resetCommunityByProdSubtypeExtProperty (ctrl , _prodSubtype, initPpfCommunity) {
			var tmpPpfCommunity;
			if (initPpfCommunity) {
				tmpPpfCommunity = initPpfCommunity;
			} else {
				tmpPpfCommunity = ctrl.ppfCommunity;
			}
			
			tmpPpfCommunity.prodSubtypeExtProperty = _prodSubtype.extProperty;
			
			/**
			 * for prod code
			 */
			var prodCodes = [];
			for (var i = 0; i < ctrl.allProdCodes.length; i++) {
				var _allProdCode = ctrl.allProdCodes[i];
				if (_allProdCode.extProperty.prodSubtype == tmpPpfCommunity.prodSubtypeExtProperty.prodSubtype) {
					prodCodes.push(_allProdCode);
				}
			}
			ctrl.prodCodeOptions = prodCodes;
			
			/**
			 * '*' means for all categories. Null means no category.  
			 * NF means for normal interest and cost-of-fund interest categories.
			 */
			var filterUfcIntCats = tmpPpfCommunity.prodSubtypeExtProperty.ufcIntCats;
			tmpPpfCommunity.interestCatShowFlag = {};
			angular.forEach(ctrl.intCatOptions, function(intCatOption) {
				var intCat = intCatOption.value;
				if (!filterUfcIntCats) {
					tmpPpfCommunity.interestCatShowFlag[intCat] = 'N';
				} else {
					if (filterUfcIntCats == '*' || filterUfcIntCats.indexOf(intCat) >= 0) {
						tmpPpfCommunity.interestCatShowFlag[intCat] = 'Y';
					} else {
						tmpPpfCommunity.interestCatShowFlag[intCat] = 'N';
					}
				}
			});	
			
			/**
			 * '*' means for all categories. Null means no category.  
			 * CI means for Credit and Insurance facility categories.
			 */
			var filterUfcFacilityCats = tmpPpfCommunity.prodSubtypeExtProperty.ufcFacilityCats;
			tmpPpfCommunity.facilityCatShowFlag = {};
			angular.forEach(ctrl.facilityCatOptions, function(facilityCatOption) {
				var facilityCat = facilityCatOption.value;
				if (!filterUfcFacilityCats) {
					tmpPpfCommunity.facilityCatShowFlag[facilityCat] = 'N';
				} else {
					if (filterUfcFacilityCats == '*' || filterUfcFacilityCats.indexOf(facilityCat) >= 0) {
						tmpPpfCommunity.facilityCatShowFlag[facilityCat] = 'Y';
					} else {
						tmpPpfCommunity.facilityCatShowFlag[facilityCat] = 'N';
					}
				}
			});
			
			
			// set aome default such as profBilling profChargeback profPayschd profInvfilter
			if (tmpPpfCommunity.dataStatus && tmpPpfCommunity.prodSubtypeExtProperty.ufcBilling == 'Y') {
				if (!tmpPpfCommunity.profBilling)
					tmpPpfCommunity.profBilling = {};
				if (!tmpPpfCommunity.profBilling.billFreqType)
					tmpPpfCommunity.profBilling.billFreqType = 'N';
				if (!tmpPpfCommunity.profBilling.billOnEomFlag)
					tmpPpfCommunity.profBilling.billOnEomFlag = 'N';
			}
			if (tmpPpfCommunity.dataStatus && tmpPpfCommunity.prodSubtypeExtProperty.ufcChargeback == 'Y') {
				if (!tmpPpfCommunity.profChargeback)
					tmpPpfCommunity.profChargeback = {};
				if (!tmpPpfCommunity.profChargeback.chargebackSetlType)
					tmpPpfCommunity.profChargeback.chargebackSetlType = 'T';
				if (!tmpPpfCommunity.profChargeback.chargebackFlag)
					tmpPpfCommunity.profChargeback.chargebackFlag = 'N';
				if (!tmpPpfCommunity.profChargeback.excludeAnchorClient)
					tmpPpfCommunity.profChargeback.excludeAnchorClient = 'N';
			}
			if (tmpPpfCommunity.dataStatus && tmpPpfCommunity.prodSubtypeExtProperty.ufcPayschd == 'Y') {
				if (!tmpPpfCommunity.profPayschd)
					tmpPpfCommunity.profPayschd = {};
				if (!tmpPpfCommunity.profPayschd.paySchdType)
					tmpPpfCommunity.profPayschd.paySchdType = 'N';
				if (!tmpPpfCommunity.profPayschd.paySchdEop)
					tmpPpfCommunity.profPayschd.paySchdEop = 'N';
			}
			if (tmpPpfCommunity.dataStatus && tmpPpfCommunity.prodSubtypeExtProperty.ufcInvfilter == 'Y') {
				if (!tmpPpfCommunity.profInvfilter)
					tmpPpfCommunity.profInvfilter = {};
				if (!tmpPpfCommunity.profInvfilter.invoiceDtmFlag)
					tmpPpfCommunity.profInvfilter.invoiceDtmFlag = 'N';
				if (!tmpPpfCommunity.profInvfilter.invoiceFutureFlag)
					tmpPpfCommunity.profInvfilter.invoiceFutureFlag = 'N';
				if (!tmpPpfCommunity.profInvfilter.invoiceAgeFlag)
					tmpPpfCommunity.profInvfilter.invoiceAgeFlag = 'N';
				if (!tmpPpfCommunity.profInvfilter.invoiceTenorFlag)
					tmpPpfCommunity.profInvfilter.invoiceTenorFlag = 'N';
				if (!tmpPpfCommunity.profInvfilter.invoiceAmtFlag)
					tmpPpfCommunity.profInvfilter.invoiceAmtFlag = 'N';
				if (!tmpPpfCommunity.profInvfilter.daysShipFlag)
					tmpPpfCommunity.profInvfilter.daysShipFlag = 'N';
				if (!tmpPpfCommunity.profInvfilter.invoiceEmdFlag)
					tmpPpfCommunity.profInvfilter.invoiceEmdFlag = 'N';
			}
		}
		
		function initProfAcct(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//init profAcct grid
			ctrl.profAcctInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.profAcct.tableConfigs.table, profAcctRowSelectionChanged);
			ctrl.profAcctInnerGridOptions.data = 'vm.ppfCommunity.profAccts';
			ctrl.profAcctInnerGridOptions.verifyData = 'vm.ppfCommunityOld.profAccts';
			// if view page, delete table checkbox
			if (!ctrl.profAcctInnerGridOptions.enableOperationRemoveSelected) {
				ctrl.profAcctInnerGridOptions.enableRowHeaderSelection = false;
			}
			function profAcctRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedProfAccts = selectedRows;
			}
			
			ctrl.addProfAcct = function(currRow) {
				return $q(function(resolved, rejected){
					// params
					var params = {};
					params.filterEventCodes = [];
					angular.forEach(ctrl.ppfCommunity.profAccts, function(profAcct, index) {
						params.filterEventCodes.push(profAcct.eventCode);
					});
					params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
					modalService.openCustomDialogs({
					   'title': 'Account Info',
					   'dialogsModule' : 'cda.profacct.popupedit',
					   'params': params,
					   'btnCallback' : {
						   'ok' : function(profAcct) {							
							   angular.merge(currRow, profAcct);
							   resolved();
							}
						}		
					});	
			   });
			};
			
			ctrl.editProfAcct = function(currRow) {
				var params = {};
				// for show selected service on popup page
				var _selectedProfAcct = currRow.entity;
				params.profAcct = angular.copy(_selectedProfAcct);
				params.filterEventCodes = [];
				angular.forEach(ctrl.ppfCommunity.profAccts, function(profAcct, index) {
					params.filterEventCodes.push(profAcct.eventCode);
				});
				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				params.updateProcessFlag  = updateProcessFlag;
				params.isEdit = 'Y';
				modalService.openCustomDialogs({
					   'title': 'Account Info',
					   'dialogsModule' : 'cda.profacct.popupedit',
					   'params': params,
					   'btnCallback' : {
							'ok' : function(profAcct) {							
								if (!ctrl.ppfCommunity.profAccts) {								
									ctrl.ppfCommunity.profAccts = [];
								}
								if (!(profAcct.dataStatus == 'C' || profAcct.dataStatus == 'U')) {
									if (updateProcessFlag) {
										profAcct.dataStatus = 'U';
									} else {
										profAcct.dataStatus = 'C';
									}
								}
								angular.extend(_selectedProfAcct, profAcct);
							}
						}		
					   
				});			
			};
			
			ctrl.viewProfAcct = function(currRow) {		
				var params = {};
				// for show selected service on popup page
				var _selectedProfAcct = currRow.entity;
				params.profAcct = angular.copy(_selectedProfAcct);
				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				//
				if (ctrl.ppfCommunityOld && ctrl.ppfCommunityOld.profAccts) {
					var oldModel4SelectedRow;
					angular.forEach(ctrl.ppfCommunityOld.profAccts, function(profAcct, index) {
						if (profAcct.eventCode == params.profAcct.eventCode) {
							oldModel4SelectedRow = profAcct;
						}
					});
					params.profAcctOld = oldModel4SelectedRow;
				}
				modalService.openCustomDialogs({
				   'title': 'Account Info',
				   'dialogsModule' : 'cda.profacct.popupview',
				   'params':params,
				   'btnCallback' : {
						'ok' : function(profAcct) {						
						}
					}		
				});
			};
			
		};
		
		
		function initMultiProfInt(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			if(ctrl.intCatOptions){
				ctrl.profIntCats = angular.copy(ctrl.intCatOptions);// for page ng-repeat
				ctrl.profIntMultiInnerGridOptions = {};
				ctrl.selectedProfInts = {};
				ctrl.addProfInt = {};
				ctrl.editProfInt = {};
				ctrl.viewProfInt = {};
				ctrl.removeProfInt = {};
				angular.forEach(ctrl.intCatOptions, function(intCatOption) {
					var intCat = intCatOption.value;
					
					//init profCostOfFundInt grid
					var profIntLayoutName = 'profInt' + intCat;
					var profIntRowSelectionChanged = {};
					profIntRowSelectionChanged[intCat] = function(eventRow, selectedRows) {
						ctrl.selectedProfInts[intCat] = selectedRows;
					}
					ctrl.profIntMultiInnerGridOptions[intCat] = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs[profIntLayoutName].tableConfigs.table, profIntRowSelectionChanged[intCat]);
					ctrl.profIntMultiInnerGridOptions[intCat].data = 'vm.ppfCommunityTmp.profInts' + intCat;
					ctrl.profIntMultiInnerGridOptions[intCat].verifyData = 'vm.ppfCommunityOldTmp.profInts' + intCat;
					// if view page, delete table checkbox
					if (!ctrl.profIntMultiInnerGridOptions[intCat].enableOperationRemoveSelected) {
						ctrl.profIntMultiInnerGridOptions[intCat].enableRowHeaderSelection = false;
					}
					
					ctrl.addProfInt[intCat] = function(currRow) {
						return $q(function(resolved, rejected){
							// params
							var params = {};
							params.filterPrimaryKeys = [];
							angular.forEach(ctrl.ppfCommunityTmp['profInts' + intCat], function(profInt, index) {
								params.filterPrimaryKeys.push(profInt.ccy + ":" + profInt.intCat);
							});
							params.profInt = {};
							params.profInt.intCat = intCat;
							params.profInt.intSpreadType = 'F';
							// prodSubtypeExtProperty
							params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
							// cda.profint.popupedit receive obj is profInt
							params.isAdd = 'Y';
							modalService.openCustomDialogs({
							   'title': ' Interest Info',
							   'dialogsModule' : 'cda.profint.popupedit',
							   'size' : [1100,500],
							   'params': params,
							   'btnCallback' : {
								   'ok' : function(profInt) {
									   // only add ctrl.ppfCommunity.profIntTmpsx
									   angular.merge(currRow, profInt);
									   // also need add in ctrl.ppfCommunity.profInts for submit service
									   if (!ctrl.ppfCommunity.profInts) ctrl.ppfCommunity.profInts = [];
									   ctrl.ppfCommunity.profInts.push(currRow);
									   resolved();
									}
								}		
							});	
					   });
					};
					
					ctrl.editProfInt[intCat] = function(currRow) {
						var params = {};
						// for show selected service on popup page
						var _selectedProfInt = currRow.entity;
						params.profInt = angular.copy(_selectedProfInt);
						params.filterPrimaryKeys = [];
						angular.forEach(ctrl.ppfCommunityTmp['profInts' + intCat], function(profInt, index) {
							params.filterPrimaryKeys.push(profInt.ccy + ":" + profInt.intCat);
						});
						params.isEdit = 'Y';
						// prodSubtypeExtProperty
						params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
						modalService.openCustomDialogs({
							   'title': ' Interest Info',
							   'dialogsModule' : 'cda.profint.popupedit',
							   'size' : [1100,500],
							   'params': params,
							   'btnCallback' : {
									'ok' : function(profInt) {							
										if (!(profInt.dataStatus == 'C' || profInt.dataStatus == 'U')) {
											if (updateProcessFlag) {
												profInt.dataStatus = 'U';
											} else {
												profInt.dataStatus = 'C';
											}
										}
										angular.extend(_selectedProfInt, profInt);
									}
								}		
							   
						});
					};
					
					ctrl.removeProfInt[intCat] = function() {		
						return $q(function(resolved, rejected){
							angular.forEach(ctrl.selectedProfInts[intCat], function(selectedProfInt, key) {
								angular.forEach(ctrl.ppfCommunity.profInts, function(profInt, index) {
									if (profInt.$$hashKey == selectedProfInt.$$hashKey) {
										if(!(profInt && profInt.dataStatus) || 'C' == profInt.dataStatus) {
											ctrl.ppfCommunity.profInts.splice(index, 1);
										} else {
											ctrl.ppfCommunity.profInts.dataStatus = 'D';
										}
									}
								});
							});
							resolved();
						});
					};
					
					ctrl.viewProfInt[intCat] = function(currRow) {		
						var params = {};
						// for show selected service on popup page
						var _selectedProfInt = currRow.entity;
						params.profInt = angular.copy(_selectedProfInt);
						// prodSubtypeExtProperty
						params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
						// for update verify
						if (ctrl.ppfCommunityOldTmp && ctrl.ppfCommunityOldTmp['profInts' + intCat]) {
							var oldModel4SelectedRow;
							angular.forEach(ctrl.ppfCommunityOldTmp['profInts' + intCat], function(oldProfInt, index) {
								// profInt.ccy + ":" + profInt.intCat
								if (oldProfInt.ccy == params.profInt.ccy && oldProfInt.intCat == params.profInt.intCat) {
									oldModel4SelectedRow = oldProfInt;
								}
							});
							params.profIntOld = oldModel4SelectedRow;
						}
						modalService.openCustomDialogs({
						   'title': ' Interest Info',
						   'dialogsModule' : 'cda.profint.popupview',
						   'size' : [1100,500],
						   'params':params,
						   'btnCallback' : {
								'ok' : function(profCostOfFundInt) {						
								}
							}		
						});
					};
					
				})
			}
		}
		
		
		function initProfPastdue(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//init profPastdue grid
			ctrl.profPastdueInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.profPastdue.tableConfigs.table, profPastdueRowSelectionChanged);
			ctrl.profPastdueInnerGridOptions.data = 'vm.ppfCommunity.profPastdues';
			ctrl.profPastdueInnerGridOptions.verifyData = 'vm.ppfCommunityOld.profPastdues';
			// if view page, delete table checkbox
			if (!ctrl.profPastdueInnerGridOptions.enableOperationRemoveSelected) {
				ctrl.profPastdueInnerGridOptions.enableRowHeaderSelection = false;
			}
			function profPastdueRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedProfPastdues = selectedRows;
			}
			
			ctrl.addProfPastdue = function(currRow) {
				return $q(function(resolved, rejected){
					// params
					var params = {};
					params.filterCcys = [];
					angular.forEach(ctrl.ppfCommunity.profPastdues, function(profPastdue, index) {
						params.filterCcys.push(profPastdue.ccy);
					});
					params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
					params.isAdd = 'Y';
					modalService.openCustomDialogs({
					   'title': 'Past Due Info',
					   'dialogsModule' : 'cda.profpastdue.popupedit',
					   'params': params,
					   'btnCallback' : {
						   'ok' : function(profPastdue) {							
							   angular.merge(currRow, profPastdue);
							   resolved();
							}
						}		
					});
			   });
			};
			
			ctrl.editProfPastdue = function(currRow) {
				var params = {};
				// for show selected service on popup page
				var _selectedProfPastdue = currRow.entity;
				params.profPastdue = angular.copy(_selectedProfPastdue);
				params.filterCcys = [];
				angular.forEach(ctrl.ppfCommunity.profPastdues, function(profPastdue, index) {
					params.filterCcys.push(profPastdue.ccy);
				});
				params.isEdit = 'Y';
				params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
				modalService.openCustomDialogs({
					   'title': 'Past Due Info',
					   'dialogsModule' : 'cda.profpastdue.popupedit',
					   'params': params,
					   'btnCallback' : {
							'ok' : function(profPastdue) {							
								if (!ctrl.ppfCommunity.profPastdues) {								
									ctrl.ppfCommunity.profPastdues = [];
								}
								if (!(profPastdue.dataStatus == 'C' || profPastdue.dataStatus == 'U')) {
									if (updateProcessFlag) {
										profPastdue.dataStatus = 'U';
									} else {
										profPastdue.dataStatus = 'C';
									}
								}
								angular.extend(_selectedProfPastdue, profPastdue);
							}
						}		
					   
				});			
			};
			
			ctrl.viewProfPastdue = function(currRow) {		
				var params = {};
				// for show selected service on popup page
				var _selectedProfPastdue = currRow.entity;
				params.profPastdue = angular.copy(_selectedProfPastdue);
				//
				if (ctrl.ppfCommunityOld && ctrl.ppfCommunityOld.profPastdues) {
					var oldModel4SelectedRow;
					angular.forEach(ctrl.ppfCommunityOld.profPastdues, function(profPastdue, index) {
						if (profPastdue.ccy == params.profPastdue.ccy) {
							oldModel4SelectedRow = profPastdue;
						}
					});
					params.profPastdueOld = oldModel4SelectedRow;
				}
				params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
				modalService.openCustomDialogs({
				   'title': 'Past Due Info',
				   'dialogsModule' : 'cda.profpastdue.popupview',
				   'params':params,
				   'btnCallback' : {
						'ok' : function(profPastdue) {						
						}
					}		
				});
			};
			
		};
		
		
		function initProfFee(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//init profFee grid
			ctrl.profFeeInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.profFee.tableConfigs.table, profFeeRowSelectionChanged);
			ctrl.profFeeInnerGridOptions.data = 'vm.ppfCommunity.profFees';
			ctrl.profFeeInnerGridOptions.verifyData = 'vm.ppfCommunityOld.profFees';
			// if view page, delete table checkbox
			if (!ctrl.profFeeInnerGridOptions.enableOperationRemoveSelected) {
				ctrl.profFeeInnerGridOptions.enableRowHeaderSelection = false;
			}
			function profFeeRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedProfFees = selectedRows;
			}
			
			ctrl.addProfFee = function(currRow) {
				return $q(function(resolved, rejected){
					//
					var bigestInEvtCcy = {};
//					angular.forEach(ctrl.ppfCommunity.profFees, function(profFee, index) {
//						var pre = bigestInEvtCcy[profFee.eventCode + ":" + profFee.ccy];
//						var now = profFee.feeCodeSeq;
//						if(pre && arithService.gt(now, pre)){
//							bigestInEvtCcy[profFee.eventCode + ":" + profFee.ccy] = now;
//						} else {
//							bigestInEvtCcy[profFee.eventCode + ":" + profFee.ccy] = now;
//						}
//					});
					angular.forEach(ctrl.ppfCommunity.profFees, function(profFee, index) {
						var pre = bigestInEvtCcy["big"];
						var now = profFee.feeCodeSeq;
						if(pre && arithService.gt(now, pre)){
							bigestInEvtCcy["big"] = now;
						} else {
							bigestInEvtCcy["big"] = now;
						}
					});
					// params
					var params = {};
					params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
					params.prodCode = ctrl.ppfCommunity.prodCode;
					params.bigestInEvtCcy = bigestInEvtCcy;
					params.profileType = 'FC';
					params.profileId = ctrl.ppfCommunity.communityId;
					params.isAdd = 'Y';
					//
					params.filterPrimaryKeys = [];
					angular.forEach(ctrl.ppfCommunity.profFees, function(profFee, index) {
						params.filterPrimaryKeys.push(profFee.ccy + ":" + profFee.eventCode + ":" + profFee.feeCode);
					});
					modalService.openCustomDialogs({
					   'title': 'Fee Info',
					   'dialogsModule' : 'cda.proffee.popupedit',
					   'size' : [1100,500],
					   'params': params,
					   'btnCallback' : {
						   'ok' : function(profFee) {							
							   angular.merge(currRow, profFee);
							   resolved();
							}
						}		
					});
			   });
			};
			
			ctrl.editProfFee = function(currRow) {
				var params = {};
				// for show selected service on popup page
				var _selectedProfFee = currRow.entity;
				params.profFee = angular.copy(_selectedProfFee);
				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				params.prodCode = ctrl.ppfCommunity.prodCode;
				params.isEdit = 'Y';
				params.profileType = 'FC';
				params.profileId = ctrl.ppfCommunity.communityId;
				//
				params.filterPrimaryKeys = [];
				angular.forEach(ctrl.ppfCommunity.profFees, function(profFee, index) {
					params.filterPrimaryKeys.push(profFee.ccy + ":" + profFee.eventCode + ":" + profFee.feeCode);
				});
				modalService.openCustomDialogs({
					   'title': 'Fee Info',
					   'dialogsModule' : 'cda.proffee.popupedit',
					   'size' : [1100,500],
					   'params': params,
					   'btnCallback' : {
							'ok' : function(profFee) {							
								if (!ctrl.ppfCommunity.profFees) {								
									ctrl.ppfCommunity.profFees = [];
								}
								if (!(profFee.dataStatus == 'C' || profFee.dataStatus == 'U')) {
									if (updateProcessFlag) {
										profFee.dataStatus = 'U';
									} else {
										profFee.dataStatus = 'C';
									}
								}
								angular.extend(_selectedProfFee, profFee);
							}
						}		
					   
				});			
			};
			
			ctrl.viewProfFee = function(currRow) {		
				var params = {};
				// for show selected service on popup page
				var _selectedProfFee = currRow.entity;
				params.profFee = angular.copy(_selectedProfFee);
				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				//
				if (ctrl.ppfCommunityOld && ctrl.ppfCommunityOld.profFees) {
					var oldModel4SelectedRow;
					angular.forEach(ctrl.ppfCommunityOld.profFees, function(profFee, index) {
						// profFee.eventCode + ":" + profFee.ccy + ":" + profFee.feeCodeSeq
						if (profFee.eventCode == params.profFee.eventCode 
						&& profFee.ccy == params.profFee.ccy 
						&& profFee.feeCodeSeq == params.profFee.feeCodeSeq) {
							oldModel4SelectedRow = profFee;
						}
					});
					params.profFeeOld = oldModel4SelectedRow;
				}
				modalService.openCustomDialogs({
				   'title': 'Fee Info',
				   'dialogsModule' : 'cda.proffee.popupview',
				   'size' : [1100,500],
				   'params':params,
				   'btnCallback' : {
						'ok' : function(profFee) {						
						}
					}		
				});
			};
			
		};
		
		
		function initEventDoccfg(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//init eventDoccfg grid
			ctrl.eventDoccfgInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.eventDoccfg.tableConfigs.table, eventDoccfgRowSelectionChanged);
			ctrl.eventDoccfgInnerGridOptions.data = 'vm.ppfCommunity.eventDoccfgs';
			ctrl.eventDoccfgInnerGridOptions.verifyData = 'vm.ppfCommunityOld.eventDoccfgs';
			// if view page, delete table checkbox
			if (!ctrl.eventDoccfgInnerGridOptions.enableOperationRemoveSelected) {
				ctrl.eventDoccfgInnerGridOptions.enableRowHeaderSelection = false;
			}
			function eventDoccfgRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedEventDoccfgs = selectedRows;
			}
			
			ctrl.addEventDoccfg = function(currRow) {
				return $q(function(resolved, rejected){
					// params
					var params = {};
					params.filterEventCodes = [];
					angular.forEach(ctrl.ppfCommunity.eventDoccfgs, function(eventDoccfg, index) {
						params.filterEventCodes.push(eventDoccfg.eventCode + ":" + eventDoccfg.docType + ":" + eventDoccfg.localeCode);
					});
					params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
					params.isAdd = 'Y';
					modalService.openCustomDialogs({
					   'title': 'Document Info',
					   'dialogsModule' : 'cda.eventdoccfg.popupedit',
					   'params': params,
					   'btnCallback' : {
						   'ok' : function(eventDoccfg) {							
							   angular.merge(currRow, eventDoccfg);
							   resolved();
							}
						}		
					});	
			   });
			};
			
			ctrl.editEventDoccfg = function(currRow) {
				var params = {};
				// for show selected service on popup page
				var _selectedEventDoccfg = currRow.entity;
				params.eventDoccfg = angular.copy(_selectedEventDoccfg);
				params.filterEventCodes = [];
				angular.forEach(ctrl.ppfCommunity.eventDoccfgs, function(eventDoccfg, index) {
					if (_selectedEventDoccfg.$$hashKey != eventDoccfg.$$hashKey) {
						params.filterEventCodes.push(eventDoccfg.eventCode + ":" + eventDoccfg.docType + ":" + eventDoccfg.localeCode);
					}
				});
				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				params.isEdit = 'Y';
				modalService.openCustomDialogs({
					   'title': 'Document Info',
					   'dialogsModule' : 'cda.eventdoccfg.popupedit',
					   'params': params,
					   'btnCallback' : {
							'ok' : function(eventDoccfg) {							
								if (!ctrl.ppfCommunity.eventDoccfgs) {								
									ctrl.ppfCommunity.eventDoccfgs = [];
								}
								if (!(eventDoccfg.dataStatus == 'C' || eventDoccfg.dataStatus == 'U')) {
									if (updateProcessFlag) {
										eventDoccfg.dataStatus = 'U';
									} else {
										eventDoccfg.dataStatus = 'C';
									}
								}
								angular.extend(_selectedEventDoccfg, eventDoccfg);
							}
						}		
					   
				});			
			};
			
			ctrl.viewEventDoccfg = function(currRow) {		
				var params = {};
				// for show selected service on popup page
				var _selectedEventDoccfg = currRow.entity;
				params.eventDoccfg = angular.copy(_selectedEventDoccfg);
				params.prodType = ctrl.ppfCommunity.prodSubtypeExtProperty.prodType;
				//
				if (ctrl.ppfCommunityOld && ctrl.ppfCommunityOld.eventDoccfgs) {
					var oldModel4SelectedRow;
					angular.forEach(ctrl.ppfCommunityOld.eventDoccfgs, function(eventDoccfg, index) {
						if (eventDoccfg.primaryKey == params.eventDoccfg.primaryKey) {
							oldModel4SelectedRow = eventDoccfg;
						}
					});
					params.eventDoccfgOld = oldModel4SelectedRow;
				}
				modalService.openCustomDialogs({
				   'title': 'Document Info',
				   'dialogsModule' : 'cda.eventdoccfg.popupview',
				   'params':params,
				   'btnCallback' : {
						'ok' : function(eventDoccfg) {						
						}
					}		
				});
			};
			
		};
		
		function initMultiProfLimitFaci(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			if(ctrl.facilityCatOptions){
				ctrl.profLimitFaciCats = angular.copy(ctrl.facilityCatOptions);// for page ng-repeat
				ctrl.profLimitFaciMultiInnerGridOptions = {};
				ctrl.selectedProfLimitFacis = {};
				ctrl.addProfLimitFaci = {};
				ctrl.editProfLimitFaci = {};
				ctrl.viewProfLimitFaci = {};
				ctrl.removeProfLimitFaci = {};
				angular.forEach(ctrl.facilityCatOptions, function(facilityCatOption) {
					var facilityCat = facilityCatOption.value;
					//init profCostOfFundLimitFaci grid
					var profLimitFaciLayoutName = 'profLimitFaci' + facilityCat;
					var profLimitFaciRowSelectionChanged = {};
					profLimitFaciRowSelectionChanged[facilityCat] = function(eventRow, selectedRows) {
						ctrl.selectedProfLimitFacis[facilityCat] = selectedRows;
					}
					ctrl.profLimitFaciMultiInnerGridOptions[facilityCat] = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs[profLimitFaciLayoutName].tableConfigs.table, profLimitFaciRowSelectionChanged[facilityCat]);
					ctrl.profLimitFaciMultiInnerGridOptions[facilityCat].data = 'vm.ppfCommunityTmp.profLimitFacis' + facilityCat;
					ctrl.profLimitFaciMultiInnerGridOptions[facilityCat].verifyData = 'vm.ppfCommunityOldTmp.profLimitFacis' + facilityCat;
					// if view page, delete table checkbox
					if (!ctrl.profLimitFaciMultiInnerGridOptions[facilityCat].enableOperationRemoveSelected) {
						ctrl.profLimitFaciMultiInnerGridOptions[facilityCat].enableRowHeaderSelection = false;
					}
					
					ctrl.addProfLimitFaci[facilityCat] = function(currRow) {
						return $q(function(resolved, rejected){
							var params = {};
							var bigestSeqInCat = {};
							angular.forEach(ctrl.ppfCommunityTmp['profLimitFacis' + facilityCat], function(profLimitFaci, index) {
								var pre = bigestSeqInCat[profLimitFaci.facilityCat];
								var now = profLimitFaci.facilitySeq;
								if(pre && arithService.gt(now, pre)){
									bigestSeqInCat[profLimitFaci.facilityCat] = now;
								} else {
									bigestSeqInCat[profLimitFaci.facilityCat] = now;
								}
							});
							params.bigestSeqInCat = bigestSeqInCat;
							params.profLimitFaci = {};
							params.profLimitFaci.facilityCat = facilityCat;
							params.isAdd = 'Y';
							modalService.openCustomDialogs({
							   'title': 'Prof LimitFaci Edit',
							   'dialogsModule' : 'cda.proflimitfaci.popupedit',
							   'params': params,
							   'btnCallback' : {
								   'ok' : function(profLimitFaci) {	
									   // only add ctrl.ppfCommunity.profLimitFaciTmpsx
									   angular.merge(currRow, profLimitFaci);
									   // also need add in ctrl.ppfCommunity.profLimitFacis for submit service
									   if (!ctrl.ppfCommunity.profLimitFacis) ctrl.ppfCommunity.profLimitFacis = [];
									   ctrl.ppfCommunity.profLimitFacis.push(currRow);
									   resolved();
									}
								}		
							});
					   });
					};
					
					ctrl.editProfLimitFaci[facilityCat] = function(currRow) {
						var params = {};
						// for show selected service on popup page
						var _selectedProfLimitFaci = currRow.entity;
						params.profLimitFaci = angular.copy(_selectedProfLimitFaci);
						params.isEdit = 'Y';
						modalService.openCustomDialogs({
							   'title': 'Prof LimitFaci Edit',
							   'dialogsModule' : 'cda.proflimitfaci.popupedit',
							   'params': params,
							   'btnCallback' : {
									'ok' : function(profLimitFaci) {							
										if (!(profLimitFaci.dataStatus == 'C' || profLimitFaci.dataStatus == 'U')) {
											if (updateProcessFlag) {
												profLimitFaci.dataStatus = 'U';
											} else {
												profLimitFaci.dataStatus = 'C';
											}
										}
										angular.extend(_selectedProfLimitFaci, profLimitFaci);
									}
								}		
						});	
					};
					
					ctrl.removeProfLimitFaci[facilityCat] = function() {		
						return $q(function(resolved, rejected){
							// remove from ctrl.ppfCommunity.profLimitFacis
							angular.forEach(ctrl.selectedProfLimitFacis[facilityCat], function(selectedProfLimitFaci, key) {
								angular.forEach(ctrl.ppfCommunity.profLimitFacis, function(profLimitFaci, index) {
									if (profLimitFaci.$$hashKey == selectedProfLimitFaci.$$hashKey) {
										if(!(profLimitFaci && profLimitFaci.dataStatus) || 'C' == profLimitFaci.dataStatus) {
											ctrl.ppfCommunity.profLimitFacis.splice(index, 1);
										} else {
											ctrl.ppfCommunity.profLimitFacis.dataStatus = 'D';
										}
									}
								});
							});
							// remove from ctrl.ppfCommunityTmp.profLimitFacis by framework
							resolved();
						});
					};
					
					ctrl.viewProfLimitFaci[facilityCat] = function(currRow) {
						var params = {};
						// for show selected service on popup page
						var _selectedProfLimitFaci = currRow.entity;
						params.profLimitFaci = angular.copy(_selectedProfLimitFaci);
						if (ctrl.ppfCommunityOldTmp && ctrl.ppfCommunityOldTmp['profLimitFacis' + facilityCat]) {
							var oldModel4SelectedRow;
							angular.forEach(ctrl.ppfCommunityOldTmp['profLimitFacis' + facilityCat], function(oldProfLimitFaci, index) {
								if (oldProfLimitFaci.profFacilityId == params.profLimitFaci.profFacilityId) {
									oldModel4SelectedRow = oldProfLimitFaci;
								}
							});
							params.profLimitFaciOld = oldModel4SelectedRow;
						}
						modalService.openCustomDialogs({
						   'title': 'Prof LimitFaci View',
						   'dialogsModule' : 'cda.proflimitfaci.popupview',
						   'params':params,
						   'btnCallback' : {
								'ok' : function(profLimitFaci) {						
								}
							}		
						});
					};
				});
			}
		}
		
		
		function initProfSetlinst(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//init profSetlinst grid
			if (ctrl.validatorConfig) {
				initLayoutConfig.formConfigs.profSetlinst.tableConfigs.table.validatorConfig = ctrl.validatorConfig.profSetlinsts;
			}
			ctrl.profSetlinstInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.profSetlinst.tableConfigs.table, profSetlinstRowSelectionChanged);
			ctrl.profSetlinstInnerGridOptions.operationRowHeaderWidth = 45;
			ctrl.profSetlinstInnerGridOptions.data = 'vm.ppfCommunity.profSetlinsts';
			ctrl.profSetlinstInnerGridOptions.verifyData = 'vm.ppfProgramOld.profSetlinsts';
			// hidden add when subline
			ctrl.profSetlinstInnerGridOptions.filterRowOperation = function(row, type){
			      if(row && row.entity && row.entity.isMaster == 'N' && type == 'add') {
			    	  return true;
			      } else {
			    	  return false;// default show
			      }
		     };
			function profSetlinstRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedProfSetlinsts = selectedRows;
			}
			
			ctrl.custAcctChanged = function (rowObj, form, isInitialized){
				ctrl.ppfCommunity.profSetlinsts = ctrl.ppfCommunity.profSetlinsts || [];
				rowObj.custAcctId = $filter('encode')(rowObj.custAcctId);
				//
				if(rowObj && !isInitialized && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			
			ctrl.txnCcyChanged = function(rowObj, form) {
				if (rowObj.txnCcy) {
					resetHiddenTxnCcy(rowObj, ctrl);
					if (!checkPrimaryKey(rowObj, ctrl)) return;
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
				
			};
			ctrl.itemTypeChanged = function(rowObj, form) {
				if (rowObj.itemType) {
					if (!checkPrimaryKey(rowObj, ctrl)) return;
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			ctrl.crDrChanged = function(rowObj, form) {
				// if setlCcy change, first clean
				rowObj.paycodeExtProperty = {};
				if (rowObj.crDr) {
					if (!checkPrimaryKey(rowObj, ctrl)) return;
					// reset paycodeOptions.data
					resetPaycodeBySetlCcyAndCrDr(rowObj, ctrl);
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			function checkPrimaryKey(rowObj, ctrl) {
				if (rowObj.txnCcy && rowObj.itemType && rowObj.crDr) {
					angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
						if (!profSetlinst.itemType || !profSetlinst.crDr || rowObj.$$hashKey == profSetlinst.$$hashKey) return;
						var filterPrimaryKey = profSetlinst.txnCcy + ":" + profSetlinst.itemType + ":" + profSetlinst.crDr;
						if ((rowObj.txnCcy + ":" + rowObj.itemType + ":" + rowObj.crDr) == filterPrimaryKey) {
							// changed eventCode has used
							if (rowObj.isMaster == 'Y') {
								rowObj.txnCcy = '';
							} else {
								rowObj.itemType = '';
								rowObj.crDr = '';
							}
							modalService.openErrorDialogs({
								messages : [ 'js.info.profsetlinst.duplicate-txnccy-itemtype-creditordebit' ]
							});
							return false;
						}
					});
				}
				return true;
			}
			function resetHiddenTxnCcy(rowObj, ctrl) {
				var currIndex;
				angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
					if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
						currIndex = index;
					}
				});
				if (currIndex + 1 < ctrl.ppfCommunity.profSetlinsts.length) {
					for (var i = currIndex + 1; i < ctrl.ppfCommunity.profSetlinsts.length; i++) {
						if (ctrl.ppfCommunity.profSetlinsts[i].isMaster == 'Y') {
							break;
						}
						ctrl.ppfCommunity.profSetlinsts[i].txnCcy = rowObj.txnCcy;
					}
				}
			}
			
			ctrl.setlCcyChanged = function(rowObj, form) {
				// if setlCcy change, first clean
				rowObj.paycodeExtProperty = {};
				// reset paycodeOptions.data
				if (rowObj.setlCcy) {
					resetPaycodeBySetlCcyAndCrDr(rowObj, ctrl);
				}
				//
				if(form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			
			function resetPaycodeBySetlCcyAndCrDr(rowObj, ctrl) {
				if (!rowObj.setlCcy || !rowObj.crDr) return;
				// filter intRateIndex by ccy
				var paycodeOptionDatas = [];
				for (var i = 0; i < ctrl.allPaycodeOptions.length; i++) {
					var _paycodeOption = ctrl.allPaycodeOptions[i];
					if ((_paycodeOption.payCcy == rowObj.setlCcy || _paycodeOption.payCcy == '*') && 
							(_paycodeOption.usedFor == 'B' || rowObj.crDr == 'B' ||  _paycodeOption.usedFor == rowObj.crDr)) {
						paycodeOptionDatas.push(ctrl.allPaycodeOptions[i]);
					}
				}
				if (rowObj._paycodeConfig && rowObj._paycodeConfig.options)
					rowObj._paycodeConfig.options.data = paycodeOptionDatas;
				if (rowObj._paycodeConfig && rowObj._paycodeConfig.options && rowObj._paycodeConfig.options.data) {
					for (var i = 0; i < rowObj._paycodeConfig.options.data.length; i++) {
						var _paycodeOption = rowObj._paycodeConfig.options.data[i];
						if (_paycodeOption.value == rowObj.paycode) {
							ctrl.paycodeChanged(rowObj);
							break;
						}
					}
				}
			}
			
			ctrl.paycodeChanged = function(rowObj, form) {
				if (rowObj.paycode) {
					resetSetlByPaycode(rowObj, ctrl, true);
				} else {
					// if no paycode, need clear
					rowObj.paycodeExtProperty = {};
					if (rowObj.isMaster != 'Y')rowObj.acctNo = '';
					rowObj.custAcctId = '';
				}
				//
				if(form && form.$dirty && 'C' != rowObj.dataStatus) {
					rowObj.dataStatus = 'U';
					rowObj.dataStatusDisp = 'U';
				}
			};
			
			function resetSetlByPaycode(rowObj, ctrl, changed) {
				if (rowObj._paycodeConfig && rowObj._paycodeConfig.options && rowObj._paycodeConfig.options.data) {
					for (var i = 0; i < rowObj._paycodeConfig.options.data.length; i++) {
						var _paycodeOption = rowObj._paycodeConfig.options.data[i];
						if (_paycodeOption.value == rowObj.paycode) {
							rowObj.paycodeExtProperty = _paycodeOption;
							// if "Y", acctNo is Customer Account Type
							if (rowObj.paycodeExtProperty.custAcctFlag == 'N') {
								rowObj.acctNo = rowObj.paycodeExtProperty.acctNo;
								rowObj.custAcctId = '';
							} else if (rowObj.paycodeExtProperty.custAcctFlag == 'Y') {
								rowObj.custAcctType = rowObj.paycodeExtProperty.acctNo;
								if (changed) {
									if (rowObj.isMaster != 'Y' && !rowObj.custAcctId)
										rowObj.acctNo = '';// if change need clear, but if init need contain
								}
							}
							break;
						}
					}
				}
			}
			
			ctrl.isDefaultChanged = function(rowObj) {
				if (rowObj.isDefault && rowObj.isDefault.length == 1 && rowObj.isDefault[0] == 'Y') {
					ctrl.ppfCommunity.defSetlinstTxnCcy = rowObj.txnCcy;
					// other must 'N'
					angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
						if (profSetlinst.$$hashKey != rowObj.$$hashKey) {
							profSetlinst.isDefault = [];
						}
					});
				}
			}
			
			ctrl.acctNoMoreData = function (rowObj){
				var params = {};
				// for get dynaparm page
				params.custAcctId = rowObj.custAcctId;
				if (!params.custAcctId) {
					modalService.openErrorDialogs({
						messages : [ 'js.info.profsetlinst.account-need-first-select' ]
					});
					return;
				}
				modalService.openCustomDialogs({
				   'title': 'Cust Acct',
				   'dialogsModule' : 'cda.custacct.popupview',
				   'params': params,
				   'btnCallback' : {
						'ok' : function(resultList) {
						}
					}	
				});
			};
			
			ctrl.addProfSetlinst = function() {
				return $q(function(resolved, rejected){
					if (!ctrl.ppfCommunity.profSetlinsts) {
						ctrl.ppfCommunity.profSetlinsts = [];
					}
					for (var i = 0; i < ctrl.ppfCommunity.profSetlinsts.length; i++) {
						var rowObj = ctrl.ppfCommunity.profSetlinsts[i];
						if (!rowObj.txnCcy) {
							modalService.openErrorDialogs({
								messages : [ 'js.info.profsetlinst.txnccy-need-first-select' ]
							});
							return;
						}
					}
					// add master
					ctrl.ppfCommunity.profSetlinsts.push({
						dataStatus : 'C',
						dataStatusDisp : '',
						isMaster : 'Y',
						// for validation
						itemType : 'N',
						crDr : 'N',
						setlCcy : 'N',
						paycode : 'N',
						acctNo : 'N'
					});
					// add sub line
					var newSubLine = {
						txnCcy : '',
						dataStatus : 'C',
						dataStatusDisp : 'C',
						isMaster : 'N',
						_paycodeConfig : {
						     model : "paycode",
						     type : "select",
						     options : {
						    	 "callback":{"changed" : "vm.paycodeChanged"}
						     },
						     show: "row.entity.isMaster == 'N'",
						     uppercase : true
						}
					};
					ctrl.ppfCommunity.profSetlinsts.push(newSubLine);
					rejected();
				});
			};
			
			ctrl.removeProfSetlinst = function(currRow) {
				return $q(function(resolved, rejected){
					var rowObj = currRow.entity;
					if (rowObj.isMaster == 'Y') {
						deleteMasterLine(ctrl, rowObj);
					} else {
						ctrl.deleteSubLine(rowObj);
					}
					rejected();
				});
			};
			
			 function deleteMasterLine(ctrl, rowObj) {
				var needDeleteRows = [];
				needDeleteRows.push(rowObj);
				angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
					if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
						rowObj.index = index;
					}
				});
				if (rowObj.isMaster == 'Y' && rowObj.index + 1 < ctrl.ppfCommunity.profSetlinsts.length) {
					for (var j = rowObj.index + 1; j < ctrl.ppfCommunity.profSetlinsts.length; j++) {
						if (ctrl.ppfCommunity.profSetlinsts[j].isMaster == 'Y')
							break;
						needDeleteRows.push(ctrl.ppfCommunity.profSetlinsts[j]);
					}
				}
				angular.forEach(needDeleteRows, function(selectedProfSetlinst, key) {
					angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
						if (profSetlinst.$$hashKey == selectedProfSetlinst.$$hashKey) {
							if (profSetlinst.dataStatus =='C') {
								ctrl.ppfCommunity.profSetlinsts.splice(index, 1);
							} else {
								profSetlinst.dataStatus = 'D';
								profSetlinst.dataStatusDisp = 'D';
							}
						}
					});
				});
				
				deleteMasterNoSub(ctrl);
			};
			
			ctrl.addSubLine = function (currRow){
				return $q(function(resolved, rejected){
					var rowObj = currRow.entity;
					if (!rowObj.txnCcy) {
						modalService.openErrorDialogs({
							messages : [ 'js.info.profsetlinst.txnccy-need-first-select' ]
						});
						return;
					}
					var currIndex;
					angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
						if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
							currIndex = index;
						}
					});
					var nextMasterRowIndex;
					if (currIndex + 1 < ctrl.ppfCommunity.profSetlinsts.length) {
						for (var i = currIndex + 1; i < ctrl.ppfCommunity.profSetlinsts.length; i++) {
							if (ctrl.ppfCommunity.profSetlinsts[i].isMaster == 'Y') {
								nextMasterRowIndex = i;
								break;
							}
						}
					}
					if (!nextMasterRowIndex) nextMasterRowIndex = ctrl.ppfCommunity.profSetlinsts.length;
					var newSubLine = {
						txnCcy : rowObj.txnCcy,
						dataStatus : 'C',
						dataStatusDisp : 'C',
						isMaster : 'N',
						_paycodeConfig : {
						     model : "paycode",
						     type : "select",
						     options : {
						    	 "callback":{"changed" : "vm.paycodeChanged"}
						     },
						     show: "row.entity.isMaster == 'N'",
						     uppercase : true
						}
					};
					ctrl.ppfCommunity.profSetlinsts.splice(nextMasterRowIndex, 0, newSubLine);
					rejected();
				});
			};
			
			ctrl.deleteSubLine = function (rowObj){
				angular.forEach(ctrl.ppfCommunity.profSetlinsts, function(profSetlinst, index) {
					if (profSetlinst.$$hashKey == rowObj.$$hashKey) {
						if (profSetlinst.dataStatus =='C') {
							ctrl.ppfCommunity.profSetlinsts.splice(index, 1);
						} else {
							profSetlinst.dataStatus = 'D';
							profSetlinst.dataStatusDisp = 'D';
						}
					}
				});
				
				deleteMasterNoSub(ctrl);
			};
			
			// after delete, need check hsa master but no sub, need delete it 
			function deleteMasterNoSub(ctrl) {
				if (ctrl.ppfCommunity.profSetlinsts) {
					var lastTxnCcy = '';
					for (var i = ctrl.ppfCommunity.profSetlinsts.length - 1; i >= 0; i--) {
						var profSetlinst = ctrl.ppfCommunity.profSetlinsts[i];
						if (profSetlinst.isMaster == 'Y' && profSetlinst.txnCcy && (profSetlinst.txnCcy != lastTxnCcy)) {
							ctrl.ppfCommunity.profSetlinsts.splice(i, 1);
						}
						
						lastTxnCcy = profSetlinst.txnCcy;
					}
				}
			}
		};
		
		// update reset for page show
		function resetSetlinstByData(initPpfCommunity, isView) {
			var initProfSetlinsts = initPpfCommunity.profSetlinsts;
			var needProfSetlinstModels = [];
			var txnCcyMap = {};
			angular.forEach(initProfSetlinsts, function(profSetlinst, index) {
				// real data and add _paycodeConfig
				profSetlinst.isMaster = 'N';
				profSetlinst._paycodeConfig = {
						model : "paycode",
						type : "select",
						options : {
							"callback":{"changed" : "vm.paycodeChanged"}
						},
						show: "row.entity.isMaster == 'N'",
						uppercase : true
				};
				profSetlinst.dataStatusDisp = profSetlinst.dataStatus;
				if (isView) profSetlinst._paycodeConfig.readonly = true;
				// txnCcyMap
				if (txnCcyMap[profSetlinst.txnCcy]) {
					txnCcyMap[profSetlinst.txnCcy].push(profSetlinst);
				} else {
					txnCcyMap[profSetlinst.txnCcy] = [];
					txnCcyMap[profSetlinst.txnCcy].push(profSetlinst);
				}
			});
			
			// build virtual master line
			angular.forEach(txnCcyMap, function(txnCcyMapValue, key) {
				var profSetlinstMaster = {};
				profSetlinstMaster.isMaster = 'Y';
				profSetlinstMaster.txnCcy = key;
				if (initPpfCommunity.defSetlinstTxnCcy && initPpfCommunity.defSetlinstTxnCcy == key) {
					profSetlinstMaster.isDefault = [];
					profSetlinstMaster.isDefault[0] = 'Y';
				}
				var txnCcyProfSetlinsts = txnCcyMap[key];
				for (var i = 0; i < txnCcyProfSetlinsts.length; i++) {
					var txnCcyProfSetlinst = txnCcyProfSetlinsts[i];
					if ("V" == txnCcyProfSetlinst.dataStatus || "U" == txnCcyProfSetlinst.dataStatus || "D" == txnCcyProfSetlinst.dataStatus) {
						profSetlinstMaster.dataStatus = "V";
						break;
					}
				}
				// itemType : 'N', crDr : 'N', setlCcy : 'N', paycode : 'N', acctNo : 'N',
				profSetlinstMaster.itemType = 'N';
				profSetlinstMaster.crDr = 'N';
				profSetlinstMaster.setlCcy = 'N';
				profSetlinstMaster.paycode = 'N';
				profSetlinstMaster.acctNo = 'N';
				needProfSetlinstModels.push(profSetlinstMaster);
				for (var i = 0; i < txnCcyProfSetlinsts.length; i++) {
					needProfSetlinstModels.push(txnCcyProfSetlinsts[i]);
				}
			});
			initPpfCommunity.profSetlinsts = needProfSetlinstModels;
		}
		
		
		function initPpfMember(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//init ppfMember grid
			ctrl.ppfMemberInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.ppfMember.tableConfigs.table, ppfMemberRowSelectionChanged);
			ctrl.ppfMemberInnerGridOptions.data = 'vm.ppfCommunity.ppfMembers';
			ctrl.ppfMemberInnerGridOptions.verifyData = 'vm.ppfCommunityOld.ppfMembers';
			function ppfMemberRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedPpfMembers = selectedRows;
			}
			
			ctrl.addPpfMember = function(currRow) {
				return $q(function(resolved, rejected){
					// params
					var params = {};
					params.filterPrimaryKeys = {'sellerCodes': [], 'memberCodes':[], 'tradepartnerIds':[]};
					angular.forEach(ctrl.ppfCommunity.ppfMembers, function(ppfMember, index) {
						params.filterPrimaryKeys.sellerCodes.push(ppfMember.sellerCode);
						params.filterPrimaryKeys.memberCodes.push(ppfMember.memberCode);
						params.filterPrimaryKeys.tradepartnerIds.push(ppfMember.tradepartnerId);
					});
					params.ppfMember = {};
					params.ppfMember.masterDataStatus = ctrl.ppfCommunity.dataStatus;
					params.ppfMember.communityId = ctrl.ppfCommunity.communityId;
					params.ppfMember.prodCode = ctrl.ppfCommunity.prodCode;
					// for unique check(buyer,seller,Community Code Qualifier,Community Code)
					params.ppfMember.communityCodeQ = ctrl.ppfCommunity.communityCodeQ;
					params.ppfMember.communityCode = ctrl.ppfCommunity.communityCode;
					params.updateProcessFlag  = updateProcessFlag;
					params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
					params.ppfCommunityBuyerCode = ctrl.ppfCommunity.buyerCode;
					params.isAdd = 'Y';
					modalService.openCustomDialogs({
					   'title': 'PPFMember Edit',
					   'dialogsModule' : 'cda.ppfmember.popupedit',
					   'size' : [1100,500],
					   'params': params,
					   'btnCallback' : {
						   'ok' : function(ppfMember) {							
							   angular.extend(currRow, ppfMember);
							   resolved();
							}
						}		
					});	
			    });
			};
			
			ctrl.editPpfMember = function(currRow) {
				var params = {};
				// for show selected service on popup page
				var _selectedPpfMember = currRow.entity;
				params.ppfMember = angular.copy(_selectedPpfMember);
				params.ppfMember.masterDataStatus = ctrl.ppfCommunity.dataStatus;
				// for unique check(buyer,seller,Community Code Qualifier,Community Code)
				params.ppfMember.communityCodeQ = ctrl.ppfCommunity.communityCodeQ;
				params.ppfMember.communityCode = ctrl.ppfCommunity.communityCode;
				params.filterPrimaryKeys = {'sellerCodes': [], 'memberCodes':[], 'tradepartnerIds':[]};
				angular.forEach(ctrl.ppfCommunity.ppfMembers, function(ppfMember, index) {
					if (_selectedPpfMember.$$hashKey != ppfMember.$$hashKey) {
						params.filterPrimaryKeys.sellerCodes.push(ppfMember.sellerCode);
						params.filterPrimaryKeys.memberCodes.push(ppfMember.memberCode);
						params.filterPrimaryKeys.tradepartnerIds.push(ppfMember.tradepartnerId);
					}
				});
				params.isEdit = 'Y';
				params.updateProcessFlag  = updateProcessFlag;
				params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
				params.ppfCommunityBuyerCode = ctrl.ppfCommunity.buyerCode;
				modalService.openCustomDialogs({
					   'title': 'PPFMember Edit',
					   'dialogsModule' : 'cda.ppfmember.popupedit',
					   'size' : [1100,500],
					   'params': params,
					   'btnCallback' : {
							'ok' : function(ppfMember) {							
								if (!ctrl.ppfCommunity.ppfMembers) {								
									ctrl.ppfCommunity.ppfMembers = [];
								}
								if (!(ppfMember.dataStatus == 'C' || ppfMember.dataStatus == 'U')) {
									if (updateProcessFlag) {
										ppfMember.dataStatus = 'U';
									} else {
										ppfMember.dataStatus = 'C';
									}
								}
								angular.extend(_selectedPpfMember, ppfMember);
							}
						}		
					   
				});			
			};
			
			ctrl.viewPpfMember = function(currRow) {		
				var params = {};
				// for show selected service on popup page
				var _selectedPpfMember = currRow.entity;
				params.ppfMember = angular.copy(_selectedPpfMember);
				params.ppfMember.masterDataStatus = ctrl.ppfCommunity.dataStatus;
				//
				if (ctrl.ppfCommunityOld && ctrl.ppfCommunityOld.ppfMembers) {
					var oldModel4SelectedRow;
					angular.forEach(ctrl.ppfCommunityOld.ppfMembers, function(ppfMember, index) {
						if (ppfMember.primaryKey == params.ppfMember.primaryKey) {
							oldModel4SelectedRow = ppfMember;
						}
					});
					params.ppfMemberOld = oldModel4SelectedRow;
				}
				params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
				modalService.openCustomDialogs({
				   'title': 'PPFMember View',
				   'dialogsModule' : 'cda.ppfmember.popupview',
				   'size' : [1100,500],
				   'params':params,
				   'btnCallback' : {
						'ok' : function(ppfMember) {						
						}
					}		
				});
			};
			
			
			ctrl.viewEffectiveSetting = function(rowObj) {		
				var params = {};
				// for show selected service on popup page
				var _selectedPpfMember;
				angular.forEach(ctrl.ppfCommunity.ppfMembers, function(ppfMember, index) {
					if (ppfMember.$$hashKey == rowObj.$$hashKey) {
						_selectedPpfMember = ppfMember;
					}
				});
				_selectedPpfMember.isEffectiveSettingSelected = 'Y';
				params.ppfCommunity = ctrl.ppfCommunity;
				params.prodSubtypeExtProperty = ctrl.ppfCommunity.prodSubtypeExtProperty;
				modalService.openCustomDialogs({
				   'title': 'PPFEffective Setting View',
				   'dialogsModule' : 'cda.ppfeffectivesetting.popupview',
				   'size' : [1100,500],
				   'params':params,
				   'btnCallback' : {
						'ok' : function() {						
						}
					}		
				});
			};
		};
		
		function initCustProp(initLayoutConfig, $scope, ctrl, updateProcessFlag) {
			//
			ctrl.selectedPropertyInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.customerProfile.tableConfigs.tableSele, customerProfileSeleRowSelectionChanged);
			ctrl.selectedPropertyInnerGridOptions.data = 'vm.ppfCommunity.ppfCommunityProps';//dynamicParams
			ctrl.selectedPropertyInnerGridOptions.verifyData = 'vm.ppfCommunityOld.ppfCommunityProps';
			ctrl.selectedPropertyInnerGridOptions.multiSelect = true;
			function customerProfileSeleRowSelectionChanged(eventRow, selectedRows) {
				ctrl.selectedCustPropSeleRows = selectedRows;
			}
			
			if (initLayoutConfig.formConfigs.customerProfile.tableConfigs.tableAvai) {
				ctrl.hasAvailablePropertyInnerGrid = 'Y';//edit page is 'Y', view page is 'N'
				ctrl.availablePropertyInnerGridOptions = gridService.createInnerGridOptions($scope, initLayoutConfig.formConfigs.customerProfile.tableConfigs.tableAvai, customerProfileAvaiRowSelectionChanged);
				ctrl.availablePropertyInnerGridOptions.data = 'vm.availableProperties';
				ctrl.availablePropertyInnerGridOptions.multiSelect = true;
				function customerProfileAvaiRowSelectionChanged(eventRow, selectedRows) {
					ctrl.selectedCustPropAvaiRows = selectedRows;
				}
			}
			
			//
			ctrl.addPpfCommunityProp = function(){
				if (!ctrl.selectedCustPropAvaiRows || ctrl.selectedCustPropAvaiRows.length == 0) {
					modalService.openErrorDialogs({
						messages : [ 'title.dialogs.info.norecsel' ]
					});
					return;
				}
				if (!ctrl.ppfCommunity.dynamicParams) {								
					ctrl.ppfCommunity.dynamicParams = {};
				}
				angular.forEach(ctrl.selectedCustPropAvaiRows, function(selectedCustPropAvai, key) {
					angular.forEach(ctrl.availableProperties, function(availableProperty, index) {
						if (availableProperty.$$hashKey == selectedCustPropAvai.$$hashKey) {
							ctrl.availableProperties.splice(index, 1);
							// some new add not in site.dynamicParams, so need put it in
							if (!ctrl.ppfCommunity.dynamicParams[availableProperty.name] || !ctrl.ppfCommunity.dynamicParams[availableProperty.name].value) {
								ctrl.ppfCommunity.dynamicParams[availableProperty.name] = availableProperty;
								angular.merge(availableProperty, availableProperty.dynamicParameter);
							}
							// change 
							var corProf = angular.copy(availableProperty);
							corProf.dynamicParams = {};
							corProf.dynamicParams[availableProperty.name] = availableProperty;
							ctrl.ppfCommunity.ppfCommunityProps.push(corProf);
						}
					});
				});
				
				ctrl.selectedCustPropAvaiRows = [];
				
			};

			ctrl.removePpfCommunityProp = function(){
				if (!ctrl.selectedCustPropSeleRows || ctrl.selectedCustPropSeleRows.length == 0) {
					modalService.openErrorDialogs({
						messages : [ 'title.dialogs.info.norecsel' ]
					});
					return;
				}
				angular.forEach(ctrl.selectedCustPropSeleRows, function(selectedParam, key) {
					angular.forEach(ctrl.ppfCommunity.ppfCommunityProps, function(ppfCommunityProp, index) {
						if (ppfCommunityProp.$$hashKey == selectedParam.$$hashKey) {
							// clear for delete, 
							delete ctrl.ppfCommunity.dynamicParams[ppfCommunityProp.name];
							
							ctrl.ppfCommunity.ppfCommunityProps.splice(index, 1);
							ctrl.availableProperties.push(ppfCommunityProp);
						}
					});
				});
				
				// if not do, after of remove item's items value would be clear
				var orgProps = angular.copy(ctrl.ppfCommunity.ppfCommunityProps);
				ctrl.ppfCommunity.ppfCommunityProps = [];
				$timeout(function(){
					ctrl.ppfCommunity.ppfCommunityProps = orgProps;
				});
				
				ctrl.selectedCustPropSeleRows = [];
			};
			
			ctrl.resetCustProperties = function () {
				resetSelectedProperties();
				resetAvailableProperties();
			};
			
			function resetSelectedProperties () {
				if (!ctrl.ppfCommunity.ppfCommunityProps) {								
					ctrl.ppfCommunity.ppfCommunityProps = [];
				}
				//ctrl.ppfCommunity.ppfCommunityProps
				var dynamicParams = ctrl.ppfCommunity.dynamicParams;
				if (dynamicParams) {
					angular.forEach(dynamicParams, function(dynamicParam, key) {
						// some new add prop or exist prop, then remove, also commit to server but value is empty, so need add '&& dynamicParam.value' to check
						if (dynamicParam.category == 'PPFCUSTOMERPROFILE' && dynamicParam.value) {
							ctrl.ppfCommunity.ppfCommunityProps.push(dynamicParam);
						}
					});
				}
				
				//
				if (ctrl.ppfCommunityOld) {
					if (!ctrl.ppfCommunityOld.ppfCommunityProps) {								
						ctrl.ppfCommunityOld.ppfCommunityProps = [];
					}
					//ctrl.ppfCommunity.ppfCommunityProps
					var oldDynamicParams = ctrl.ppfCommunityOld.dynamicParams;
					if (oldDynamicParams) {
						angular.forEach(oldDynamicParams, function(dynamicParam, key) {
							// some new add prop or exist prop, then remove, also commit to server but value is empty, so need add '&& dynamicParam.value' to check
							if (dynamicParam.category == 'PPFCUSTOMERPROFILE' && dynamicParam.value) {
								// change, build some dynaparm define
								var corProf = angular.copy(dynamicParam);
								// need dynamicParameter.name and dynamicParameter.dispKey
								corProf.dynamicParameter = angular.copy(dynamicParam);
//								// value is such as dynamicParams.CDA_DYNAPARM2.value
//								corProf.dynamicParams = {};
//								corProf.dynamicParams[dynamicParam.name] = dynamicParam;
//								corProf.model = 'dynamicParams.'+ dynamicParam.name +'.value';
								ctrl.ppfCommunityOld.ppfCommunityProps.push(corProf);
							}
						});
					}
				}
			}
			
			function resetAvailableProperties () {
				// change layoutConfig, get subCata 'CUSTOMERPROFILE'
				var custProfAvaiProps = [];
				var gridConfigs = ctrl.layoutConfig.formConfigs.customerProfile.gridConfigs;
				if (gridConfigs) {
					angular.forEach(gridConfigs, function(gridConfig, key) {
						if (gridConfig.dynamicParameter && gridConfig.dynamicParameter.category == 'PPFCUSTOMERPROFILE') {
							//
							var _gridConfig = angular.copy(gridConfig);
							var hasInSele = false;
							if (ctrl.ppfCommunity.ppfCommunityProps && ctrl.ppfCommunity.ppfCommunityProps.length > 0) {
								for (var i = 0; i < ctrl.ppfCommunity.ppfCommunityProps.length; i++) {
									var ppfCommunityProp = ctrl.ppfCommunity.ppfCommunityProps[i];
									if ($filter("encode")(ppfCommunityProp.id) == $filter("encode")(_gridConfig.dynamicParameter.id)) {
										hasInSele = true;
										delete ppfCommunityProp.label;
										// change 
										var layoutAndValue = _gridConfig;
										layoutAndValue.dynamicParams = {};
										layoutAndValue.dynamicParams[ppfCommunityProp.name] = ppfCommunityProp;
										// only for update verify
										layoutAndValue.primaryKey = ppfCommunityProp.primaryKey;
										layoutAndValue.value = ppfCommunityProp.value;
										ctrl.ppfCommunity.ppfCommunityProps[i] = layoutAndValue;
										break;
									}
								}
							}
							if (!hasInSele)
								custProfAvaiProps.push(_gridConfig);
							//this will in tab cust Profile, not show other place
							gridConfig.show = false;
						}
					});
				}
				// some has value but not has layout dynaparm, need clear
				if (ctrl.ppfCommunity.ppfCommunityProps && ctrl.ppfCommunity.ppfCommunityProps.length > 0) {
					for (var i = ctrl.ppfCommunity.ppfCommunityProps.length - 1; i >= 0 ; i--) {
						var ppfCommunityProp = ctrl.ppfCommunity.ppfCommunityProps[i];
						if (!ppfCommunityProp.dynamicParams) {
							ctrl.ppfCommunity.ppfCommunityProps.splice(i, 1);
						}
					}
				}
				ctrl.availableProperties = custProfAvaiProps;
				
				sortDynamicParamters(ctrl.ppfCommunity.ppfCommunityProps);
				sortDynamicParamters(ctrl.availableProperties);
			};

			function sortDynamicParamters(serviceDymamicParamters){
				if(!serviceDymamicParamters){
					return;
				}
				serviceDymamicParamters.sort(function(p1, p2){
					return arithService.gt(p1.dynamicParameter.dispOrder, p2.dynamicParameter.dispOrder) ? 1 : -1;
				});
			}
		}
		
		
		// if no this tab, data need clear
		function clearDirtyData (ctrl) {
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcBilling == 'Y')) {
				delete ctrl.ppfCommunity.profBilling;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcChargeback == 'Y')) {
				delete ctrl.ppfCommunity.profChargeback;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcPayschd == 'Y')) {
				delete ctrl.ppfCommunity.profPayschd;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcInvfilter == 'Y')) {
				delete ctrl.ppfCommunity.profInvfilter;
			}
			//
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcAccount == 'Y')) {
				delete ctrl.ppfCommunity.profAccts;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcPastdue == 'Y')) {
				delete ctrl.ppfCommunity.profPastdues;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcFee == 'Y')) {
				delete ctrl.ppfCommunity.profFees;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcDoc == 'Y')) {
				delete ctrl.ppfCommunity.eventDoccfgs;
			}
			if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.prodSubtypeExtProperty.ufcSetlinst == 'Y')) {
				delete ctrl.ppfCommunity.profSetlinsts;
			}
			
			angular.forEach(ctrl.intCatOptions, function(intCatOption) {
				var intCat = intCatOption.value;
				if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.interestCatShowFlag[intCat] == 'Y')) {
					if (ctrl.ppfCommunity.profInts && ctrl.ppfCommunity.profInts.length > 0) {
						for (var j = ctrl.ppfCommunity.profInts.length - 1; j >= 0; j--) {
							if (ctrl.ppfCommunity.profInts[j].intCat == intCat) {
								// delete
								ctrl.ppfCommunity.profInts.splice(j, 1);
							}
						}
					}
				}
			});
			
			angular.forEach(ctrl.facilityCatOptions, function(facilityCatOption) {
				var facilityCat = facilityCatOption.value;
				if (!(ctrl.ppfCommunity.dataStatus && ctrl.ppfCommunity.facilityCatShowFlag[facilityCat] == 'Y')) {
					if (ctrl.ppfCommunity.profLimitFacis && ctrl.ppfCommunity.profLimitFacis.length > 0) {
						for (var j = ctrl.ppfCommunity.profLimitFacis.length - 1; j >= 0; j--) {
							if (ctrl.ppfCommunity.profLimitFacis[j].facilityCat == facilityCat) {
								// delete
								ctrl.ppfCommunity.profLimitFacis.splice(j, 1);
							}
						}
					}
				}
			});
			
			// delete build virtual master line when submit to server
			var ppfCommunity = ctrl.ppfCommunity;
			if (ppfCommunity.profSetlinsts != null && ppfCommunity.profSetlinsts.length > 0) {
				for (var i = ppfCommunity.profSetlinsts.length - 1; i >= 0; i--) {
					if ("Y" == ppfCommunity.profSetlinsts[i].isMaster) {
						ppfCommunity.profSetlinsts.splice(i, 1);
					}
				}
			}
		}
		
		function initOptions(ctrl) {
			var defer1 = $q.defer();
			var defer2 = $q.defer();
			ajaxService.getCommunityStatusOptions().then(function(response) {
				ctrl.communityStatusOptions = response.data;
				defer1.resolve();
			});
			ajaxService.getCommunityCodeQOptions().then(function(response) {
				ctrl.communityCodeQOptions = response.data;
				defer2.resolve();
			});
			return $q.all({
				defer1 : defer1.promise,
				defer2 : defer2.promise
			});
		}
		
		return {
			initGeneral : initGeneral,
			initLayoutConfigAndModel : initLayoutConfigAndModel,
			initProfAcct : initProfAcct,
			initProfPastdue : initProfPastdue,
			initProfFee : initProfFee,
			initEventDoccfg : initEventDoccfg,
			initProfSetlinst : initProfSetlinst,
			initPpfMember : initPpfMember,
			initCustProp : initCustProp,
			clearDirtyData : clearDirtyData,
			initOptions : initOptions
		};
	}
})(angular);
